package algorithms;

import java.util.ArrayList;
import java.util.Comparator;

import base.GenericSearch;
import datastructures.CityData;
import datastructures.MyNode;

public class AStarSearch extends GenericSearch  {
	CityData data; //must be generic, like Data data -> CityData implements Data or extends Data ...
	ArrayList<MyNode> route;

	public AStarSearch(Comparator<MyNode> comp, CityData cityData) {
		super(comp);
		this.data = cityData;
		this.route = new ArrayList<MyNode>();
	}

	//haengt alle noch nicht untersuchten knoten an die openlist an und setzt bei bedarf die g, h, f werte neu
	@Override
	public void insert(ArrayList<MyNode> nodes) {
		ArrayList<MyNode> childs = new ArrayList<MyNode>();
		boolean tentativeIsBetter = false;
		
		for (MyNode child : nodes) {
			double tentativeGScore = this.getCurrentNode().getG() + child.getCost();
			
			if (!this.openlist.contains(child)) {
				childs.add(child);
				tentativeIsBetter = true;
			} else if (tentativeGScore < child.getG()) {
				tentativeIsBetter = true;
				
			} else {
				tentativeIsBetter = false;
				
			}
			
			if (tentativeIsBetter) {
				child.setParent(this.getCurrentNode());
				child.setG(tentativeGScore);
				child.setH(getHeuristic(child, (String)this.getTarget()));
				child.setF(child.getG() + child.getH());
				
			}
			
		}
		
		this.openlist.add(childs);
		
	}
	
	//luftlinie berechnen
	public double getHeuristic(MyNode thisNode, String target) {
		int x = Math.abs(data.getData(thisNode.getName()).getX() - data.getData(target).getX());
		int y = Math.abs(data.getData(thisNode.getName()).getY() - data.getData(target).getY());
		
		return Math.sqrt(x * x + y * y);
		
	}
	
	public void printRoute() {
		
		
	}
	
	//returns route from start to target as MyNode ArrayList
	public ArrayList<MyNode> getRouteRecursiv(MyNode node) {
		if (node.getParent() != null) {
			getRouteRecursiv(node.getParent());
			route.add(node);
		} else {
			route.add(node);
			
		}
		return this.route;
	}
	
	
	@Override
	public MyNode investigate() {
		return this.openlist.getFirstNode();
		
	}

}
